#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

#endregion

namespace Weazel.Gezel.Model
{
  /// <summary>
  /// The Port class provides the common base for the InPort and
  /// OutPort types.
  /// </summary>
  public abstract class Port : AbstractEntity<CommonEntity>, ITypedEntity, IComparable<Port>
  {
    /// <summary>
    /// The position of this port in the
    /// declaration port list. Used to
    /// connect datapaths from system
    /// declarations.
    /// </summary>
    private int declarationPosition;
		public virtual int DeclarationPosition
		{
			get { return declarationPosition; }
			set { declarationPosition = value; }
		}

    /// <summary>
    /// The bitwidth of the port.
    /// </summary>
    private int width;
    public int Width
    {
      get { return width; }
			protected set { width = value; }
    }

    /// <summary>
    /// True iff the port is read as a
    /// two's complement integer.
    /// </summary>
    private bool signed;
    public bool Signed
    {
      get { return signed; }
			protected set { signed = value; }      
    }

    /// <summary>
    /// Constructs a new port with an ipblock as parent.
    /// </summary>
    /// <param name="parent">parent ip-block</param>
    /// <param name="name">local name</param>
    /// <param name="width">port width in bits</param>
    /// <param name="signed">true iff the contents are signed</param>
    /// <param name="pos">port declaration position</param>
    protected Port(IPBlock parent, string name, int width, bool signed, int pos) : base(parent, name)
    {      
      this.width = width;
      this.signed = signed;
      this.DeclarationPosition = pos;
    }

		protected Port(
			IPBlock parent, 
			string name, 
			int width, 
			bool signed, 
			int pos,
			Position startPosition,
			Position endPosition
		)
			: base(parent, name, startPosition, endPosition)
    {
      this.width = width;
      this.signed = signed;
      this.DeclarationPosition = pos;
    }

		protected Port(Datapath parent, string name, int pos)
			: base(parent, name)
		{
			this.declarationPosition = pos;
		}

		protected Port(IPBlock parent, string name, int pos)
			: base(parent, name)
		{
			this.declarationPosition = pos;
		}

    /// <summary>
    /// Constructs a new port with a datapath as parent.
    /// </summary>
    /// <param name="parent">parent ip-block</param>
    /// <param name="name">local name</param>
    /// <param name="width">port width in bits</param>
    /// <param name="signed">sign</param>
    /// <param name="pos">port declaration position</param>
    protected Port(Datapath parent, string name, int width, bool signed, int pos) : base(parent, name)
    {
      this.width = width;
      this.signed = signed;
      this.DeclarationPosition = pos;
    }

		protected Port(
			Datapath parent, 
			string name, 
			int width, 
			bool signed, 
			int pos,
			Position startPosition,
			Position endPosition
		)
			: base(parent, name, startPosition, endPosition)
    {
      this.width = width;
      this.signed = signed;
      this.DeclarationPosition = pos;
    }

    public bool Equals(Port port)
    {
      return this == port;
    }

    public int CompareTo(Port port)
    {
      if (declarationPosition < port.declarationPosition)
        return -1;
      else if (declarationPosition > port.declarationPosition)
        return 1;
      else
        return 0;
    }
  }
}
